// Package client
// Created by GoLand
// @User: lenora
// @Date: 2024/8/27
// @Time: 16:48

package client

import (
	intrv1 "camp/microbook/api/proto/gen/interactive"
	"context"
	"github.com/ecodeclub/ekit/syncx/atomicx"
	"google.golang.org/grpc"
	"math/rand"
)

type InteractiveClient struct {
	remote intrv1.InteractiveServiceClient
	local  intrv1.InteractiveServiceClient

	threshold *atomicx.Value[int32]
}

func NewInteractiveClient(remote intrv1.InteractiveServiceClient, local intrv1.InteractiveServiceClient) *InteractiveClient {
	return &InteractiveClient{remote: remote, local: local, threshold: atomicx.NewValue[int32]()}
}

// selectClient  选择要使用的调用模式
// 取[0,100)的随机数,
// 通过threshold与随机数的大小值比较实现远程调用与本地调用的分流控制
// 两种调用方式可以同时使用
// @receiver c
// @return intrv1.InteractiveServiceClient
func (c *InteractiveClient) selectClient() intrv1.InteractiveServiceClient {
	//取[0,100)的随机数
	num := rand.Int31n(100)
	if num < c.threshold.Load() {
		return c.remote
	}
	return c.local
}

func (c *InteractiveClient) UpdateThreshold(threshold int32) {
	c.threshold.Store(threshold)
}

func (c *InteractiveClient) IncrReadCnt(ctx context.Context, in *intrv1.IncrReadCntReq, opts ...grpc.CallOption) (*intrv1.Response, error) {
	return c.selectClient().IncrReadCnt(ctx, in, opts...)
}

func (c *InteractiveClient) IncrLikeCnt(ctx context.Context, in *intrv1.LikeCntReq, opts ...grpc.CallOption) (*intrv1.Response, error) {
	return c.selectClient().IncrLikeCnt(ctx, in, opts...)
}

func (c *InteractiveClient) DecrLikeCnt(ctx context.Context, in *intrv1.LikeCntReq, opts ...grpc.CallOption) (*intrv1.Response, error) {
	return c.selectClient().DecrLikeCnt(ctx, in, opts...)
}

func (c *InteractiveClient) Collect(ctx context.Context, in *intrv1.CollectReq, opts ...grpc.CallOption) (*intrv1.Response, error) {
	return c.selectClient().Collect(ctx, in, opts...)
}

func (c *InteractiveClient) Get(ctx context.Context, in *intrv1.GetReq, opts ...grpc.CallOption) (*intrv1.GetResp, error) {
	return c.selectClient().Get(ctx, in, opts...)
}

func (c *InteractiveClient) GetByIds(ctx context.Context, in *intrv1.GetByIdsReq, opts ...grpc.CallOption) (*intrv1.GetByIdsResp, error) {
	return c.selectClient().GetByIds(ctx, in, opts...)
}
